from sys import argv
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *

# 第三周 第一节 中点法画圆


class MyPyOpenGLTest:
    # 初始化OpenGL环境，指定显示模式以及用于绘图的函数
    def __init__(self, width=640, height=480,
                 title='中点算法画圆'.encode('gbk')):
        glutInit(argv)
        # 使用RGBA颜色、双缓冲
        glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH)
        # 设置图形窗口初始大小和位置，然后创建图形窗口，顺序不能变
        glutInitWindowSize(width, height)
        glutInitWindowPosition(400, 200)
        glutCreateWindow(title)
        # 指定绘制图形时执行的方法
        glutDisplayFunc(self.draw)
        # 指定调整窗口大小时执行的方法
        glutReshapeFunc(self.reshape)
        # 指定系统空闲时执行的方法
        # glutIdleFunc(self.draw)
        # 进一步初始化，完成个性化设置
        self.InitGL(width, height)

    # 根据特定的需要，进一步完成OpenGL的初始化
    def InitGL(self, width, height):
        # 初始化窗口背景为白色
        glClearColor(1.0, 1.0, 1.0, 1.0)
        # 切换到透视投影矩阵
        glMatrixMode(GL_PROJECTION)
        # 加载单位矩阵，重置
        glLoadIdentity()
        gluOrtho2D(0, width, 0, height)
        # 切换到模型观察矩阵
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()

    # 调整图形窗口大小时执行的方法
    def reshape(self, w, h):
        if h == 0:
            h = 1
        ratio = w / h
        # 设置视口/视区的左下角x、y坐标以及窗口宽度和高度
        # 视口是最终用来显示图形的区域
        glViewport(0, 0, w, h)
        # 切换到透视投影矩阵
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        # 设置世界窗口的左下角x坐标、右上角x坐标、左下角y坐标、右上角y坐标
        # 这是需要显示到视口的图形区域
        # gluOrtho2D(0, w, 0, h)
        # 设置窗口
        gluOrtho2D(-w/2, w/2, -h/2, h/2)
        # 修改为下面的大小可以看到直线段被放大后像素离散的状态

        # 切换到模型观察矩阵
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()

    # 画圆
    def draw_circle_poiots(self, x0, y0, x, y):
        glVertex2f(x0+x, y0+y)
        glVertex2f(x0+y, y0+x)
        glVertex2f(x0-y, y0+x)
        glVertex2f(x0-x, y0+y)
        glVertex2f(x0-x, y0-y)
        glVertex2f(x0-y, y0-x)
        glVertex2f(x0+y, y0-x)
        glVertex2f(x0+x, y0-y)

    def draw_circle_Mid(self, x0, y0, r, color):
        x, y, = 0, round(r)
        d = round(1.25 - r)
        glColor3fv(color)
        glPointSize(1.5)
        glBegin(GL_POINTS)
        while x <= y:
            self.draw_circle_poiots(x0, y0, x, y)
            if x == y:
                break
            if d < 0:
                d = d + 2*x + 3
            else:
                d = d + 2*(x - y) + 5
                y = y - 1
            x = x + 1
        glEnd()

    # 自己的绘图方法，本程序的关键
    def draw(self):
        # 每次绘制图形之前清除颜色缓冲区和深度缓冲区中的信息
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        # 黑色
        glColor3f(0, 0, 0)
        # 切换到模型观察矩阵，才能正确绘制图形
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()
        glTranslatef(0, 0, 0)
        self.draw_circle_Mid(0, 0, 90, (0, 1, 0))
        glutSwapBuffers()

    # 消息主循环
    def mainloop(self):
        glutMainLoop()

if __name__ == '__main__':
    # 创建窗口对象，启动消息主循环
    MyPyOpenGLTest().mainloop()
